package com.xiyuan;

import com.xiyuan.annotation.Tags;
import com.xiyuan.bean.Request;
import com.xiyuan.bean.Result;
import com.xiyuan.util.ResourceUtil;
import org.springframework.web.bind.annotation.*;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


public abstract class AbstractPathBuilder {

    /**
     * 获取yml里面的数据
     */
    private static Map<String, Object> ymlData;
    /**
     * 设置命名规则
     */
    private static Map<String, String> rule;
    protected Result result = new Result();

    static {
        ymlData = ResourceUtil.getYml(AbstractPathBuilder.class);
        if (ymlData != null) {
            rule = (Map<String, String>) ymlData.get("rule");
        }
    }

    /**
     * 返回builder中的result
     *
     * @return
     */
    public Result getResult() {
        return result;
    }


    /**
     * 解析参数
     *
     * @param clazz
     */
    public void parsingRequestMethodParameters(Class<?> clazz) {
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            boolean b = Arrays.stream(method.getAnnotations())
                    .anyMatch(this::isPathAnnotation);
            //方法上面已经有RequestMapping，进行查询方法内的参数
            if (b) {
                //获取方法上的参数
                Parameter[] parameters = method.getParameters();
                parsingParameters(parameters);
            }
        }
    }

    /**
     * 解析参数
     */
    public List<?> parsingParameters(Parameter[] parameters) {
        for (Parameter parameter : parameters) {

        }
        return null;
    }

    /**
     * 获取顶部路由参数
     *
     * @param clazz
     * @return
     */
    public void getRoutePath(Class<?> clazz) {
        RequestMapping annotation = clazz.getAnnotation(RequestMapping.class);
        if (annotation instanceof RequestMapping) {
            //默认返回第一个value
            result.setRoutePath(annotation.value()[0]);
        }

    }

    /**
     * 注解处理
     *
     * @param annotation 传入注解
     * @return
     */
    public List<Request> getAnnotationPath(Annotation annotation) {
        List<Request> value = new ArrayList<>();
        if (annotation instanceof RequestMapping) {
            for (String s : ((RequestMapping) annotation).value()) {
                value.add(new Request("post", s));
            }
        } else if (annotation instanceof GetMapping) {
            for (String s : ((GetMapping) annotation).value()) {
                value.add(new Request("get", s));
            }
        } else if (annotation instanceof PostMapping) {
            for (String s : ((PostMapping) annotation).value()) {
                value.add(new Request("post", s));
            }
        } else if (annotation instanceof DeleteMapping) {
            for (String s : ((DeleteMapping) annotation).value()) {
                value.add(new Request("delete", s));
            }
        } else if (annotation instanceof PutMapping) {
            for (String s : ((PutMapping) annotation).value()) {
                value.add(new Request("put", s));
            }
        } else {
            return null;
        }
        return value;

    }

    /**
     * 判断是不是路径中的参数
     *
     * @return
     */
    public boolean isPathAnnotation(Annotation annotation) {
        return annotation instanceof RequestMapping ||
                annotation instanceof DeleteMapping ||
                annotation instanceof GetMapping ||
                annotation instanceof PostMapping ||
                annotation instanceof PutMapping;

    }

    /**
     * 按照规则对路径进行命名
     *
     * @param path
     */


    public String nameThePathAccordingToTheRules(String path) {
//        从yml中读取规则
        if (rule != null && rule.size() != 0) {
            String temp = "尚未知路径名称";
            for (Map.Entry<String, String> entry : rule.entrySet()) {
                String k = entry.getKey();
                String v = entry.getValue();
                if (ResourceUtil.checkPathContain(path, k)) {
                    return v;
                }
            }
            return temp;
        } else {
            //默认规则
            if (path.contains("get") && path.contains("id"))
                return "通过id获取";
            else if (path.contains("save")) {
                return "保存";
            } else if (path.contains("list")) {
                return "分页查询";
            } else if (path.contains("del")) {
                return "删除";
            }
        }
        return "尚未知路径名称";
    }

    public abstract void createJson();

    /**
     * 获取方法上面的注解
     *
     * @param clazz
     * @return
     */
    public void getMethodAnnotations(Class<?> clazz) {
        Method[] methods = clazz.getMethods();
        List<Annotation> list = new ArrayList<>();
        for (Method method : methods) {
            Annotation[] annotations = method.getAnnotations();
            list.addAll(Arrays.asList(annotations));
        }
        result.setMethodAnnotations(list);
    }

    public void getTags(Class<?> clazz) {
        Tags annotation = clazz.getAnnotation(Tags.class);
        //默认返回第一个value
        String value = annotation.value();
        if (value == null || value == "")
            System.out.println("注意tags属性为空，请使用类上@Tags注解给模块命名");
        result.setTags(value);
    }

    public void parseMethodAnnotations() {
        List<Annotation> methodAnnotations = result.getMethodAnnotations();
        for (Annotation methodAnnotation : methodAnnotations) {
            //判断是不是请求注解
            if (isPathAnnotation(methodAnnotation)) {
//            获取注解中的路径
                List<Request> annotationPath = getAnnotationPath(methodAnnotation);
                if (annotationPath != null)
                    result.getPathList().addAll(annotationPath);
            }
        }
    }

    public void namePath() {
        for (Request request : result.getPathList()) {
            //按照路径名称和规则对该路径进行命名
            String interfaceName = nameThePathAccordingToTheRules(request.getPath());
            result.getPathMap().put(interfaceName, request);
        }
    }
}
